﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Analytics.BusinessLogic.Rules;
using DiscoveryLogic.Analytics.BusinessLogic.Scenarios;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Networks;
using DiscoveryLogic.Analytics.DataObjects.Rules;
using DiscoveryLogic.Common.Utilities;

namespace DiscoveryLogic.Analytics.Modules.Networks
{
    /// <summary>
    /// Interaction logic for CoAuthorNetworkInMedline.xaml
    /// </summary>
    public partial class CoAuthorNetworkInMedline : UserControl
    {
        public delegate void OnNetworkCreated(Network network);
        public event OnNetworkCreated NetworkCreated;

        public delegate void OnStatusChanged(string msg, int pct);
        public event OnStatusChanged StatusChanged;

        private class BgWorkerArg
        {
            public string NetworkName;
            public List<List<string>> OrAndMeshTerms;
            public string SQL;
            public int FromYr;
            public int ToYr;
            public int MinPubsPerPerson;
            public Dictionary<string, List<string>> FlagMeshTerms;
            public EntityDedupRule PersonDedupRule;
        }

        private BackgroundWorker _BgWorker;
        private Dictionary<string, EntityDedupRule> _DedupRules;
        private Dictionary<string, EntityRelationRule> _LinkRules;
        private string _NetworkName;

        public CoAuthorNetworkInMedline()
        {
            InitializeComponent();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.cboDedupPersons.Items.Clear();
            this._DedupRules = new Dictionary<string, EntityDedupRule>();
            List<RuleBase> rules = RuleManager.GetRulesByType(RuleType.Dedup, EntityIcons.DedupRuleIcon);
            if (rules != null && rules.Count > 0)
            {
                foreach (RuleBase rule in rules)
                {
                    if (rule.SrcEntityType == EntityType.Persons)
                    {
                        this._DedupRules.Add(rule.RuleName, rule as EntityDedupRule);
                        this.cboDedupPersons.Items.Add(rule.RuleName);
                    }
                }
                if (this.cboDedupPersons.Items.Count > 0)
                    this.cboDedupPersons.SelectedIndex = 0;
            }

            this.cboFromPubYear.Items.Clear();
            this.cboToPubYear.Items.Clear();
            for (int i = 1980; i <= DateTime.Now.Year; i++)
            {
                this.cboFromPubYear.Items.Add(i.ToString());
                this.cboToPubYear.Items.Add(i.ToString());
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if (this.Parent is Window)
            {
                ((Window)this.Parent).Close();
            }
        }

        private void btnOK_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (this.cboDedupPersons.SelectedIndex < 0)
                {
                    MessageBox.Show("Define org dedup rule first");
                    return;
                }
                if (string.IsNullOrEmpty(this.txtNetworkName.Text))
                {
                    MessageBox.Show("Enter a name for network");
                    return;
                }
                if (string.IsNullOrEmpty(this.txtKeyWords.Text) && 
                    string.IsNullOrEmpty(this.txtSql.Text))
                {
                    MessageBox.Show("Enter mesh term or sql");
                    return;
                }

                this._NetworkName = this.txtNetworkName.Text;
                BgWorkerArg arg = new BgWorkerArg();
                arg.OrAndMeshTerms = new List<List<string>>();
                if(!string.IsNullOrEmpty(this.txtKeyWords.Text))
                {
                    string[] andMeshTerms = this.txtKeyWords.Text.Split(new char[] { '\n', '\r' });
                    foreach (string andMeshTerm in andMeshTerms)
                    {
                        if (andMeshTerm.Trim().Length > 0)
                        {
                            string[] meshTerms = StringUtil.Split(andMeshTerm, "AND");
                            if(meshTerms.Length>0)
                            {
                                List<string> meshTermList=new List<string>();
                                foreach(string meshTerm in meshTerms)
                                {
                                    if(meshTerm.Trim().Length>0)
                                        meshTermList.Add(meshTerm.Trim());
                                }
                                arg.OrAndMeshTerms.Add(meshTermList);
                            }
                        }
                    }
                }
                arg.NetworkName = this.txtNetworkName.Text;
                arg.PersonDedupRule = this._DedupRules[this.cboDedupPersons.SelectedItem.ToString()];
                arg.FromYr = 1970;
                arg.ToYr = DateTime.Now.Year;
                if (this.cboFromPubYear.SelectedIndex >= 0 && this.cboToPubYear.SelectedIndex >= 0)
                {
                    int fromYr = int.Parse(this.cboFromPubYear.SelectedItem.ToString());
                    int toYr = int.Parse(this.cboToPubYear.SelectedItem.ToString());
                    if (fromYr <= toYr)
                    {
                        arg.FromYr = fromYr;
                        arg.ToYr = toYr;
                    }
                }
                arg.SQL = this.txtSql.Text;
                arg.FlagMeshTerms=new Dictionary<string, List<string>>();
                if(!string.IsNullOrEmpty(this.txtFlagMeshTermsBindings.Text))
                {
                    string[] lines = this.txtFlagMeshTermsBindings.Text.Split(new char[] {'\n', '\r'});
                    foreach(string line in lines)
                    {
                        if(line.Trim().Length==0)
                            continue;
                       string[] pair = line.Trim().Split(new char[] {'='});
                        if(pair.Length==2)
                        {
                            string flag = pair[0];
                            string[] meshTerms = StringUtil.Split(pair[1], "AND");
                            List<string> meshTermList = new List<string>();
                            foreach(string meshTerm in meshTerms)
                            {
                                if(meshTerm.Trim().Length>0)
                                {
                                    meshTermList.Add(meshTerm.Trim());
                                }
                            }
                            if(meshTermList.Count>0)
                                arg.FlagMeshTerms.Add(flag, meshTermList);
                        }
                    }
                }
                arg.MinPubsPerPerson = 0;
                if (!string.IsNullOrEmpty(this.txtMinPubsPerson.Text))
                    arg.MinPubsPerPerson = int.Parse(this.txtMinPubsPerson.Text);

                this._BgWorker = new BackgroundWorker();
                this._BgWorker.WorkerReportsProgress = true;
                this._BgWorker.WorkerSupportsCancellation = true;
                this._BgWorker.ProgressChanged += new ProgressChangedEventHandler(_BgWorker_ProgressChanged);
                this._BgWorker.DoWork += new DoWorkEventHandler(_BgWorker_DoWork);
                this._BgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_BgWorker_RunWorkerCompleted);

                this._BgWorker.RunWorkerAsync(arg);

                if (this.Parent is Window)
                {
                    ((Window)this.Parent).Close();
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }

        void _BgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!string.IsNullOrEmpty(this._NetworkName))
            {
                try
                {
                    Network network = Network.Read(this._NetworkName);
                    if (network != null && this.NetworkCreated != null)
                    {
                        this.NetworkCreated(network);
                    }
                }
                catch (Exception ex)
                {
                    System.Windows.Forms.MessageBox.Show(ex.Message);
                }
            }
        }

        void _BgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                this._BgWorker.ReportProgress(10, "Creating sponsor network...");
                BgWorkerArg arg = (BgWorkerArg)e.Argument;
                Network network = null;
                if (string.IsNullOrEmpty(arg.SQL))
                {
                    network = PersonNetworkBuilder.BuildCoAuthorNetworkUsingMedlineMeshTerms(
                        arg.NetworkName, arg.OrAndMeshTerms, arg.FromYr, arg.ToYr, arg.PersonDedupRule);
                }
                else if (arg.FlagMeshTerms ==null || arg.FlagMeshTerms.Count==0)
                {
                    network = PersonNetworkBuilder.BuildCoAuthorNetworkUsingMedlineMeshTerms(
                        arg.NetworkName, arg.SQL, arg.PersonDedupRule, arg.MinPubsPerPerson);
                }
                else
                {
                    network = PersonNetworkBuilder.BuildCoAuthorNetworkWithMeshTermFlagsUsingMedlineMeshTerms(
                        arg.NetworkName, arg.SQL, arg.FlagMeshTerms, arg.PersonDedupRule, arg.MinPubsPerPerson);
                }
                network.Save();
                this._BgWorker.ReportProgress(0, "Sponsoring network created.");
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
                this._BgWorker.ReportProgress(0, ex.Message);
            }
        }

        void _BgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (this.StatusChanged != null)
            {
                this.StatusChanged(e.UserState.ToString(), e.ProgressPercentage);
            }
        }

        private void btnAddFlagMeshTerms_Click(object sender, RoutedEventArgs e)
        {
            if(!string.IsNullOrEmpty(this.txtFlagName.Text) && 
                !string.IsNullOrEmpty(this.txtFlagMeshTerms.Text))
            {
                if (!string.IsNullOrEmpty(this.txtFlagMeshTermsBindings.Text))
                    this.txtFlagMeshTermsBindings.Text += Environment.NewLine;
                this.txtFlagMeshTermsBindings.Text += string.Format(
                    "{0}={1}", this.txtFlagName.Text, this.txtFlagMeshTerms.Text);
            }
        }


    }
}
